package Server;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * This class creates a threadPool with fixed number of threads
 * Each thread finds the matched values from logFile
 * Socket and port of the server are initialized
 * @author Group6
 */
public class ThreadPooledServer implements Runnable {

	//Port and socket of the server
	protected int serverPort;
	//Server socket
	protected ServerSocket serverSocket;
	//Server stopped or not
	protected boolean isStopped;
	//Current thread
	protected Thread runningThread;
	//Number of threads from pool
	protected ExecutorService threadPool;

	public ThreadPooledServer(int port, ServerSocket serverSocket,
			boolean isStopped, Thread runningThread, int threadNumber) {
		this.serverPort = port;
		this.serverSocket = serverSocket;
		this.isStopped = isStopped;
		this.runningThread = runningThread;
		threadPool = Executors.newFixedThreadPool(threadNumber);
	}

	//Socket accepts the connections and handles them
	public void run() {
		synchronized (this) {
			this.runningThread = Thread.currentThread();
		}
		openServerSocket();
		while (true) {
			Socket clientSocket = null;
			try {
				//Listen client
				clientSocket = this.serverSocket.accept();
			} catch (IOException e) {
				if (isStopped()) {
					System.out.println("Server Stopped.");
					return;
				}
				throw new RuntimeException("Error accepting client connection",
						e);
			}
			//Take a runnable object which is NetworkServerTest
			this.threadPool.execute(new NetworkServerTest(clientSocket,
					"Thread Pooled Server"));
		}
	}

	//server closed or not
	private synchronized boolean isStopped() {
		return this.isStopped;
	}

	//close the server
	public synchronized void stop() {
		this.isStopped = true;
		try {
			this.serverSocket.close();
		} catch (IOException e) {
			throw new RuntimeException("Error closing server", e);
		}
	}

	//Server socket opened
	private void openServerSocket() {
		try {
			this.serverSocket = new ServerSocket(this.serverPort);
		} catch (IOException e) {
			throw new RuntimeException("Cannot open port 8090", e);
		}
	}

	public static void main(String args[]) {
		//Initial values are identified
		ThreadPooledServer server = new ThreadPooledServer(8090, null, false,
				null, 5);
		//run method executed in this class
		new Thread(server).start();

		//Programs running time when it lasts then program ends
		try {
			Thread.sleep(20 * 100000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Stopping Server");
		server.stop();
	}
}